/*
 * @[H]:  Copyright (c) 2021 Phytium Information Technology, Inc. 
 * 
 *  SPDX-License-Identifier: Apache-2.0. 
 * 
 * @Date: 2021-07-13 16:49:11
 * @LastEditTime: 2021-07-16 11:39:58
 * @Description:  Description of file
 * @Modify History: 
 * * * Ver   Who        Date         Changes
 * * ----- ------     --------    --------------------------------------
 */
#ifndef BSP_DRIVERS_F_SPI_H
#define BSP_DRIVERS_F_SPI_H

#ifdef __cplusplus
extern "C"
{
#endif
#include "ft_types.h"
#include "ft_assert.h"

#define FSPI_BUSY_STATUS FT_CODE_ERR(ErrModBsp, ErrBspSpi, 0x1u)
#define FSPI_OP_VALUE_ERROR_STATUS FT_CODE_ERR(ErrModBsp, ErrBspSpi, 0x2u)

#define FSPI_POLL_TRANSACTION 0
#define FSPI_INTR_TRANSACTION 1

#define FSPI_IRQ_FULL_CALLBACK_REGISTER 0
#define FSPI_IRQ_FIN_CALLBACK_REGISTER 1

#define SPI_CPHA (1ULL << 0) /* clock phase */
#define SPI_CPOL (1ULL << 1) /* clock polarity */
#define SPI_MODE_0 (0 | 0)   /* (original MicroWire) */
#define SPI_MODE_1 (0 | SPI_CPHA)
#define SPI_MODE_2 (SPI_CPOL | 0)
#define SPI_MODE_3 (SPI_CPOL | SPI_CPHA)

#define FSPI_OPTION_SPEED 0
#define FSPI_OPTION_N_BYTES 1
#define FSPI_OPTION_TRANS_MODE 2
#define FSPI_OPTION_WORK_MODE 3

    typedef void (*FSpiIrqCallBack)(void *args);

    typedef struct
    {
        u32 instance_id; /* Id of device*/
        volatile uintptr_t base_address;
        u32 module_frequency; // Module frequency
        u32 irq_num;          // Irq number
        u32 tx_fifo_len;      // Tx fifo max length
        u32 work_mode;        // Followed by FSPI_POLL_TRANSACTION,FSPI_INTR_TRANSACTION
        u32 spi_trans_mode;   // Followed by SPI_MODE_x
        u32 n_bytes;          // Transfer 1 is byte , 2 is half word
    } FSpiConfig;

    typedef struct
    {
        u32 is_ready; /* Device is ininitialized and ready*/
        u32 is_busy;  /* Device is busy , 1 is busy*/
        FSpiConfig config;

        u32 length;              // Need Transfer length
        void *send_buffer_p;     // Buffer to send
        void *recv_buffer_p;     // Buffer to receive
        void *send_buffer_end_p; // Buffer to send
        void *recv_buffer_end_p; // Buffer to receive

        // irq
        FSpiIrqCallBack fspi_full_callback; //
        void *full_args;

        FSpiIrqCallBack fspi_recv_fin_callback; //
        void *recv_args;

    } FSpi;

    void FSpiInterruptHandler(s32 vector, FSpi *instance_p);
    ft_error_t FSpiSetOptions(FSpi *instance_p, u32 options, u32 value);
    ft_error_t FSpiTransfer(FSpi *instance_p, void *tx_buf, void *rx_buf, fsize_t length);
    FSpiConfig *FspiLookupConfig(u32 instance_id);
    void FSpiIrqCallbackRegister(FSpi *instance_p, u32 select_index, FSpiIrqCallBack callback_fun, void *arg);
    ft_error_t FSpiCfgInitialize(FSpi *instance_p, FSpiConfig *config_p);
#ifdef __cplusplus
}
#endif

#endif // !